/******************************************************************************

	COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2010.

	This file is part of the Maxsi Library.

	Maxsi Library is free software: you can redistribute it and/or modify it
	under the terms of the GNU Lesser General Public License as published by
	the Free Software Foundation, either version 3 of the License, or (at your
	option) any later version.

	Maxsi Library is distributed in the hope that it will be useful, but
	WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
	or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
	License for more details.

	You should have received a copy of the GNU Lesser General Public License
	along with Maxsi Library. If not, see <http://www.gnu.org/licenses/>.

	Maxsi Library
	A powerful Cross-Platform C++ General Purpose Library that allows you to
	efficiently create high-performance and reliable applications.

	MaxsiIO.h
	A Simple Flexible Async I/O System.

******************************************************************************/

#ifdef Maxsi_Support_MaxsiIO

#ifndef MaxsiIO_H
#define MaxsiIO_H

BeginMaxsiNamespace

//=============================================================================
//	Forward declarations.
//=============================================================================
class	MaxsiIODevice;
class	MaxsiIOEntity;
struct	MaxsiIOHandle;
typedef	MaxsiIOHandle* MaxsiIOSocket;

//=============================================================================
//	Flags for various bitmasks.
//=============================================================================
#define MAXSI_IO_SUPPORTS_NETWORK			(1<<0)
#define MAXSI_IO_SUPPORTS_FILESYSTEM		(1<<1)
#define MAXSI_IO_SUPPORTS_VIRTUAL_SOCKETS	(1<<2)
#define MAXSI_IO_SUPPORTS_ASYNC				(1<<3)
#define MAXSI_IO_SUPPORTS_NON_BLOCKING		(1<<4)
#define MAXSI_IO_SUPPORTS_MAIN_LOOP			(1<<5)
#define MAXSI_IO_SUPPORTS_THREADS			(1<<6)
#define MAXSI_IO_SUPPORTS_NORMAL_MODE_IN	(1<<7)
#define MAXSI_IO_SUPPORTS_NORMAL_MODE_OUT	(1<<8)
#define MAXSI_IO_SUPPORTS_NORMAL_MODE		(MAXSI_IO_SUPPORTS_NORMAL_MODE_IN | MAXSI_IO_SUPPORTS_NORMAL_MODE_OUT)
#define MAXSI_IO_SUPPORTS_REVERSE_MODE_IN	(1<<9)
#define MAXSI_IO_SUPPORTS_REVERSE_MODE_OUT	(1<<10)
#define MAXSI_IO_SUPPORTS_REVERSE_MODE		(MAXSI_IO_SUPPORTS_REVERSE_MODE_IN | MAXSI_IO_SUPPORTS_REVERSE_MODE_OUT)
#define MAXSI_IO_SUPPORTS_MULTIPLE_SOCKETS	(1<<11)
#define MAXSI_IO_SUPPORTS_DEVICE_READ		(1<<12)
#define MAXSI_IO_SUPPORTS_DEVICE_WRITE		(1<<13)

#define MAXSI_IO_SOCKET_IS_INCOMING			(1<<0)
#define MAXSI_IO_SOCKET_IS_OUTGOING			(1<<1)
#define MAXSI_IO_SOCKET_IS_NORMAL			(1<<2)
#define MAXSI_IO_SOCKET_IS_REVERSE			(1<<3)

#define MAXSI_IO_READ_COMPLETED				(1<<0)
#define MAXSI_IO_WRITE_COMPLETED			(1<<1)
#define MAXSI_IO_READ_POSSIBLE				(1<<2)
#define MAXSI_IO_WRITE_POSSIBLE				(1<<3)

#define MAXSI_IO_IS_SERVER					(1<<0)
#define MAXSI_IO_IS_SOCKET_LISTENER			(1<<1)

#define MAXSI_IO_DIRECTION_READ				(0)
#define MAXSI_IO_DIRECTION_WRITE			(1)

//=============================================================================
//	MaxsiIOHandle - A struct that contains meta-data linking a connection with
//	a device.
//=============================================================================
STRUCTLINK MaxsiIOHandle
{
	MaxsiIOEntity*		Connection;
	MaxsiIOSocket*		Socket;
	MaxsiIODevice*		Device;
	MaxsiBuffer*		Buffer;
	Word_t				Direction;
#ifdef Maxsi_Support_POSIX
	int	FD;
#endif
};

//=============================================================================
//	Define where the MaxsiIODevice interface is declared.
//=============================================================================
#undef MAXSI_INTERFACE
#define MAXSI_INTERFACE MAXSI_INTERFACE_IMPLEMENTED_IN_MAXSI_LIBRARY

//=============================================================================
//	MaxsiIODevice - An endpoint in a MaxsiIOEntity chain.
//=============================================================================
CLASSLINK MaxsiIODevice
{
public:
	MAXSI_DECLARE_CLASS(MaxsiIODevice);

//=============================================================================
//	Copy-pasteable interface MaxsiIODevice from starts here.
//=============================================================================
public:
	virtual FLAGSL32 GetCapabilities() MAXSI_INTERFACE;

public:
	virtual MaxsiIOHandle* AllocateIOHandle() MAXSI_INTERFACE;
	virtual MaxsiError DeleteIOHandle(MaxsiIOHandle* Handle) MAXSI_INTERFACE;

public:
	virtual MaxsiError MainLoop() MAXSI_INTERFACE;

public:
	virtual MaxsiError HandleOpenDevice(MaxsiIOEntity* Remote, MaxsiIOSocket* Socket, Word_t Direction) MAXSI_INTERFACE;
	virtual MaxsiError HandleListen(MaxsiIOEntity* Remote, MaxsiIOSocket* Socket, short Port) MAXSI_INTERFACE;
	virtual MaxsiError HandleConnect(MaxsiIOEntity* Remote, MaxsiIOSocket* Socket, MESTR* HostName, short Port) MAXSI_INTERFACE;
	virtual MaxsiError HandleOpenFile(MaxsiIOEntity* Remote, MaxsiIOSocket* Socket, MESTR* Path, FLAGS32 Mode) MAXSI_INTERFACE; 
	virtual MaxsiError HandleAccept(MaxsiIOEntity* Remote, MaxsiIOSocket* Socket, MaxsiIOSocket ListenSocket) MAXSI_INTERFACE;

public:
	virtual MaxsiError HandleDisconnect(MaxsiIOSocket* Socket) MAXSI_INTERFACE;

public:
	virtual MaxsiError SetUpAsyncIOHandleCallbacks(MaxsiIOSocket* Connection) MAXSI_INTERFACE;
	virtual MaxsiError AttemptRead(MaxsiIOHandle* Connection, BYTE* Buffer, size_t* BufferSize, size_t* Transferred) MAXSI_INTERFACE;
	virtual MaxsiError AttemptWrite(MaxsiIOHandle* Connection, BYTE* Buffer, size_t* BufferSize, size_t* Transferred) MAXSI_INTERFACE;

};

//=============================================================================
//	Define where the MaxsiIOEntity interface is declared.
//=============================================================================
#undef MAXSI_INTERFACE
#define MAXSI_INTERFACE MAXSI_INTERFACE_IMPLEMENTED_IN_MAXSI_LIBRARY

//=============================================================================
//	MaxsiIOEntity - A link in a chain of IO handlers.
//=============================================================================
CLASSLINK MaxsiIOEntity : public MaxsiIODevice, public MaxsiThinks
{
public:
	MAXSI_DECLARE_CHILD_CLASS(MaxsiIOEntity, MaxsiIODevice);

public:
	MaxsiIOEntity();
	virtual ~MaxsiIOEntity();

public:
	MaxsiBuffer*	NIBuf;
	MaxsiBuffer*	NOBuf;
	MaxsiBuffer*	RIBuf;
	MaxsiBuffer*	ROBuf;

public:
	MaxsiIOHandle*	NI;
	MaxsiIOHandle*	NO;
	MaxsiIOHandle*	RI;
	MaxsiIOHandle*	RO;
 
//=============================================================================
//	Copy-pasteable interface from MaxsiIOEntity starts here.
//=============================================================================
public:
	virtual MaxsiError CreateBuffers() MAXSI_INTERFACE;
	virtual MaxsiError DeleteBuffers() MAXSI_INTERFACE;
	virtual MaxsiError CreateBuffers(MaxsiIOSocket* Socket) MAXSI_INTERFACE;
	virtual MaxsiError DeleteBuffers(MaxsiIOSocket* Socket) MAXSI_INTERFACE;

public:
	virtual FLAGSL32 GetSocketCapabilities(MaxsiIOSocket* Socket) MAXSI_INTERFACE;
	virtual size_t GetSocketEndpoints(MaxsiIOSocket* Socket, MaxsiIOSocket** Output, size_t OutputLength) MAXSI_INTERFACE;
	virtual size_t GetIncomingSockets(MaxsiIOSocket** Output, size_t OutputLength) MAXSI_INTERFACE;
	virtual size_t GetOutgoingSockets(MaxsiIOSocket** Output, size_t OutputLength) MAXSI_INTERFACE;
	virtual MaxsiIOSocket* GetNormalIncoming() MAXSI_INTERFACE;
	virtual MaxsiIOSocket* GetNormalOutgoing() MAXSI_INTERFACE;
	virtual MaxsiIOSocket* GetReverseIncoming() MAXSI_INTERFACE;
	virtual MaxsiIOSocket* GetReverseOutgoing() MAXSI_INTERFACE;

public:
	virtual MaxsiError NotifyOpen(MaxsiIOSocket* Socket, FLAGSL32 State) MAXSI_INTERFACE;
	virtual MaxsiError NotifyClose(MaxsiIOSocket* Socket, FLAGSL32 State) MAXSI_INTERFACE;
	virtual MaxsiError NotifyRead(MaxsiIOSocket* Socket, FLAGSL32 State) MAXSI_INTERFACE;
	virtual MaxsiError NotifyWrite(MaxsiIOSocket* Socket, FLAGSL32 State) MAXSI_INTERFACE;
	virtual MaxsiError NotifyIncomingConnection(MaxsiIOSocket* Socket, FLAGSL32 State) MAXSI_INTERFACE;

public:
	virtual MaxsiError ReadConnection(MaxsiIOHandle* Connection, MaxsiBuffer* Buffer) MAXSI_INTERFACE;

//=============================================================================
//	Copy-pasteable interface MaxsiThinks from starts here.
//=============================================================================
public:
	virtual MaxsiError OnThink() MAXSI_INTERFACE;


//=============================================================================
//	Copy-pasteable interface MaxsiIODevice from starts here.
//=============================================================================
public:
	virtual FLAGSL32 GetCapabilities() MAXSI_INTERFACE;

public:
	virtual MaxsiIOHandle* AllocateIOHandle() MAXSI_INTERFACE;
	virtual MaxsiError DeleteIOHandle(MaxsiIOHandle* Handle) MAXSI_INTERFACE;

public:
	virtual MaxsiError MainLoop() MAXSI_INTERFACE;

public:
	virtual MaxsiError HandleOpenDevice(MaxsiIOEntity* Remote, MaxsiIOSocket* Socket, Word_t Direction) MAXSI_INTERFACE;
	virtual MaxsiError HandleListen(MaxsiIOEntity* Remote, MaxsiIOSocket* Socket, short Port) MAXSI_INTERFACE;
	virtual MaxsiError HandleConnect(MaxsiIOEntity* Remote, MaxsiIOSocket* Socket, MESTR* HostName, short Port) MAXSI_INTERFACE;
	virtual MaxsiError HandleOpenFile(MaxsiIOEntity* Remote, MaxsiIOSocket* Socket, MESTR* Path, FLAGS32 Mode) MAXSI_INTERFACE; 
	virtual MaxsiError HandleAccept(MaxsiIOEntity* Remote, MaxsiIOSocket* Socket, MaxsiIOSocket ListenSocket) MAXSI_INTERFACE;

public:
	virtual MaxsiError HandleDisconnect(MaxsiIOSocket* Socket) MAXSI_INTERFACE;

public:
	virtual MaxsiError AttemptRead(MaxsiIOHandle* Connection, BYTE* Buffer, size_t* BufferSize, size_t* Transferred) MAXSI_INTERFACE;
	virtual MaxsiError AttemptWrite(MaxsiIOHandle* Connection, BYTE* Buffer, size_t* BufferSize, size_t* Transferred) MAXSI_INTERFACE;

};

//=============================================================================
//	Locks.
//=============================================================================
MaxsiError IOLockConnectivity();
MaxsiError IOUnlockConnectivity();

//=============================================================================
//	Connectivity functions.
//=============================================================================
MaxsiError IOConnectToDevice(MaxsiIOEntity* From, MaxsiIOSocket* FromSocket, MaxsiIODevice* Device, Word_t Direction);
MaxsiError IOConnectToFileSystem(MaxsiIOEntity* From, MaxsiIOSocket* FromSocket, MaxsiIODevice* Device, MESTR* Path, FLAGS32 Mode);
MaxsiError IOListenOnDevice(MaxsiIOEntity* From, MaxsiIOSocket* FromSocket, MaxsiIODevice* Device, short Port);
MaxsiError IOAcceptFromDevice(MaxsiIOEntity* Dest, MaxsiIOSocket* DestSocket, MaxsiIODevice* Device, MaxsiIOSocket ListenSocket);
MaxsiError IOConnectToSocket(MaxsiIOEntity* From, MaxsiIOSocket* FromSocket, MaxsiIOEntity* Dest, MaxsiIOSocket* DestSocket);
MaxsiError IOConnectNormalOneWay(MaxsiIOEntity* From, MaxsiIOEntity* Dest);
MaxsiError IOConnectReverseOneWay(MaxsiIOEntity* From, MaxsiIOEntity* Dest);
MaxsiError IOConnectNormalTwoWay(MaxsiIOEntity* From, MaxsiIOEntity* Dest);
MaxsiError IOConnectReverseTwoWay(MaxsiIOEntity* From, MaxsiIOEntity* Dest);
MaxsiError IODisconnectSocket(MaxsiIOSocket* Socket);
MaxsiError IODeleteSocket(MaxsiIOSocket Socket);

EndMaxsiNamespace

#endif

#endif

